unit Utils;

interface

uses System.SysUtils, Winapi.Windows, System.Classes, Vcl.Dialogs, ceflib;

type
  TMyCefUrlrequestClientOwn = class;

  TMyCefResourceHandle = class(TCefResourceHandlerOwn)
  private
    FOffset: Integer;
    FTotal: Integer;
    FResource: TMemoryStream;

    FWebRequest: ICefUrlRequest;
    FWebRequestClient: TMyCefUrlrequestClientOwn;
    FFinished: Boolean;
  protected
    function ProcessRequest(const request: ICefRequest; const callback: ICefCallback): Boolean; override;
    procedure GetResponseHeaders(const response: ICefResponse; out responseLength: Int64; out redirectUrl: ustring); override;
    function ReadResponse(const dataOut: Pointer; bytesToRead: Integer; var bytesRead: Integer; const callback: ICefCallback): Boolean; override;
    function CanGetCookie(const cookie: PCefCookie): Boolean; override;
    function CanSetCookie(const cookie: PCefCookie): Boolean; override;
    procedure Cancel; override;
  public
    constructor Create(const browser: ICefBrowser; const frame: ICefFrame;
      const schemeName: ustring; const request: ICefRequest); override;
    destructor Destroy; override;
  end;

  TMyCefUrlrequestClientOwn = class(TCefUrlrequestClientOwn)
  private
    FResourceHandle: TMyCefResourceHandle;
  protected
    procedure OnRequestComplete(const request: ICefUrlRequest); override;
    procedure OnUploadProgress(const request: ICefUrlRequest; current, total: UInt64); override;
    procedure OnDownloadProgress(const request: ICefUrlRequest; current, total: UInt64); override;
    procedure OnDownloadData(const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt); override;
  public
    constructor Create; override;
  end;

var
  _responseHeadersReadyCallback: ICefCallback;

implementation

{ TMyCefResourceHandle }

procedure TMyCefResourceHandle.Cancel;
begin
  inherited;
  // CefRuntimeTracker.LogMsg('TMyCefResourceHandle.Cancel');
end;

function TMyCefResourceHandle.CanGetCookie(

  const cookie: PCefCookie): Boolean;
begin
  // CefRuntimeTracker.LogMsg('TMyCefResourceHandle.CanGetCookie');
end;

function TMyCefResourceHandle.CanSetCookie(

  const cookie: PCefCookie): Boolean;
begin
  // CefRuntimeTracker.LogMsg('TMyCefResourceHandle.CanSetCookie');
end;

constructor TMyCefResourceHandle.Create(const browser: ICefBrowser; const frame: ICefFrame;
  const schemeName: ustring; const request: ICefRequest);
begin
  inherited;
  // CefRuntimeTracker.LogMsg('TMyCefResourceHandle.Create');
  FResource := TMemoryStream.Create;
  FFinished := False;
end;

destructor TMyCefResourceHandle.Destroy;
begin
  FWebRequest := nil;
  FResource.Clear;
  FResource.Free;
  inherited;
end;

procedure TMyCefResourceHandle.GetResponseHeaders(const response: ICefResponse;
  out responseLength: Int64; out redirectUrl: ustring);
var
  stringMap: ICefStringMultimap;
  I: Integer;
  webResponse: ICefRequest;
  webresp: ICefResponse;
begin
  inherited;
  responseLength := -1;
  Assert(CefCurrentlyOn(TID_IO));

//  webresp := FWebRequest.GetResponse;
//
//  if webresp <> nil then
//  begin
//    stringMap := TCefStringMultimapOwn.Create;
//
//    webresp.GetHeaderMap(stringMap);
//
//    for I := 0 to stringMap.Size - 1 do
//      ShowMessage(stringMap.Key[I] + ': ' + stringMap.Value[I]);
//
//    stringMap := nil;
//  end;


  webResponse := FWebRequest.GetRequest;// .GetResponse;
  if webResponse <> nil then
  begin
    stringMap := TCefStringMultimapOwn.Create;

    webResponse.GetHeaderMap(stringMap);

    for I := 0 to stringMap.Size - 1 do
      OutputDebugString(PWideChar(stringMap.Key[I] + ': ' + stringMap.Value[I]));

    response.SetHeaderMap(stringMap);
    response.Status := response.Status;
    response.StatusText := response.StatusText;

//    if (webResponse.MimeType <> '') then
//    begin
//      response.MimeType := webResponse.MimeType;
//    end;
//    responseLength := webResponse.MimeType;
    stringMap := nil;

//  response_length = _content.size();
//    _offset = 0;
  end;
end;

function TMyCefResourceHandle.ProcessRequest(const request: ICefRequest; const callback: ICefCallback): Boolean;
begin
  FResource.Clear;
  FOffset := 0;
  // 1. Start the request using WebRequest
  // 2. Return True to handle the request
  // 3. Once response headers are ready call
  // callback.Continue()

  FWebRequestClient := TMyCefUrlrequestClientOwn.Create;
  FWebRequestClient.FResourceHandle := Self;

  request.Flags := [UR_FLAG_ALLOW_CACHED_CREDENTIALS];
  // | UR_FLAG_ALLOW_COOKIES);
  //
  // To skip cache :
  // | request.SetFlags(cefpython.Request.Flags["SkipCache"])
  // Must keep a strong reference to the WebRequest() object.
//  FWebRequest := TCefUrlRequestRef.New(request, FWebRequestClient);

//  FWebRequest.

  callback.Cont;

  Result := True;
end;

function TMyCefResourceHandle.ReadResponse(const dataOut: Pointer;
  bytesToRead: Integer; var bytesRead: Integer;
  const callback: ICefCallback): Boolean;
var
  url: string;
begin
  url := StringReplace(FWebRequest.GetRequest.Url, '/', '\', [rfReplaceAll]);
  OutputDebugString(PWideChar('>>>ReadResponse' + FWebRequest.GetRequest.Url));

  if (Self.FResource.Size = 0) or (not FFinished) then
  begin
    Result := True;
    callback.Cont;
    Exit;
  end;

  if FOffset < Self.FResource.Size then
  begin
    bytesRead := FResource.Read(dataOut^, bytesToRead);
    FOffset := FOffset + bytesRead;
    Result := True;
    callback.Cont;

//    if FOffset > 1000 then
//    begin
//      Result := False;
//    end;
  end
  else
    Result := False;
end;

{ TMyCefUrlrequestClientOwn }

constructor TMyCefUrlrequestClientOwn.Create;
begin
  inherited;

end;

procedure TMyCefUrlrequestClientOwn.OnDownloadData(const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
begin
  inherited;

  if FResourceHandle.FWebRequest <> nil then

  OutputDebugString(PWideChar('data: >>>' + FResourceHandle.FWebRequest.GetRequest.Url));
  FResourceHandle.FResource.Write(data, dataLength);
end;

procedure TMyCefUrlrequestClientOwn.OnDownloadProgress(const request: ICefUrlRequest; current, total: UInt64);
begin
  inherited;
  FResourceHandle.FTotal := total;
end;

procedure TMyCefUrlrequestClientOwn.OnRequestComplete(const request: ICefUrlRequest);
var
  url: string;
begin
  inherited;
  url := StringReplace(request.GetRequest.Url, '/', '\', [rfReplaceAll]);
  OutputDebugString(PWideChar('>>>finished' + request.GetRequest.Url));
  FResourceHandle.FResource.SaveToFile('c:\' + IntToStr(Random(100)));//ExtractFileName(url));
  FResourceHandle.FResource.Position := 0;
  FResourceHandle.FFinished := True;
  FResourceHandle.FTotal := FResourceHandle.FResource.Size;
end;

procedure TMyCefUrlrequestClientOwn.OnUploadProgress(const request: ICefUrlRequest; current, total: UInt64);
begin
  inherited;

end;

end.
